package org.truenewx.tnxjee.repo.jdbc.flyway;

import org.flywaydb.core.api.configuration.ClassicConfiguration;
import org.flywaydb.core.api.configuration.Configuration;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.flywaydb.core.api.migration.JavaMigration;
import org.flywaydb.core.api.resource.LoadableResource;
import org.flywaydb.core.internal.scanner.LocationScannerCache;
import org.flywaydb.core.internal.scanner.ResourceNameCache;
import org.flywaydb.core.internal.scanner.Scanner;
import org.truenewx.tnxjee.core.Strings;
import org.truenewx.tnxjee.core.util.CollectionUtil;
import org.truenewx.tnxjee.core.util.LogUtil;
import org.truenewx.tnxjee.core.version.Version;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * 迁移扫描器
 *
 * @author jianglei
 */
public class MigrationScanner extends Scanner<JavaMigration> {

    private final Configuration configuration;

    public MigrationScanner(Configuration configuration) {
        super(JavaMigration.class,
                false,
                new ResourceNameCache(),
                new LocationScannerCache(),
                configuration);
        this.configuration = configuration;
    }

    public static MigrationScanner of(Configuration configuration) {
        MigrationScanner scanner = new MigrationScanner(configuration);
        if (configuration instanceof ClassicConfiguration cc) {
            cc.setResourceProvider(scanner);
            cc.setJavaMigrationClassProvider(scanner);
        } else if (configuration instanceof FluentConfiguration fc) {
            fc.resourceProvider(scanner);
            fc.javaMigrationClassProvider(scanner);
        }
        return scanner;
    }

    public String getLatestVersion() {
        List<Version> versions = new ArrayList<>();
        String prefix = this.configuration.getSqlMigrationPrefix();
        Collection<LoadableResource> resources = getResources(prefix, this.configuration.getSqlMigrationSuffixes());
        resources.forEach(resource -> versions.add(getVersion(prefix, resource)));
        Collection<Class<? extends JavaMigration>> classes = getClasses();
        classes.forEach(clazz -> {
            try {
                JavaMigration migration = clazz.getConstructor().newInstance();
                String versionValue = migration.getVersion().toString();
                versions.add(new Version(versionValue));
            } catch (Exception e) {
                LogUtil.warn(getClass(), e.getMessage());
            }
        });
        Collections.sort(versions);
        Version version = CollectionUtil.getLast(versions, null);
        return version == null ? null : version.toText(true);
    }

    private Version getVersion(String prefix, LoadableResource resource) {
        String filename = resource.getFilename();
        String version = filename.substring(prefix.length(), filename.lastIndexOf(Strings.DOT));
        return new Version(version);
    }

}
